package com.library.management.entity;

import com.library.management.enums.NotificationPriority;
import com.library.management.enums.NotificationType;
import jakarta.persistence.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

/**
 * 通知消息实体类
 * 管理系统向用户发送的各种通知消息
 *
 * 关联关系：
 * - 多对一：用户
 *
 * 业务功能：
 * - 消息通知管理
 * - 消息状态跟踪
 * - 过期消息清理
 *
 * @author 开发者
 * @version 1.0
 * @since 2025-10-19
 */
@Entity
@Table(name = "notifications", indexes = {
        @Index(name = "idx_notifications_user_id", columnList = "user_id"),
        @Index(name = "idx_notifications_type", columnList = "type"),
        @Index(name = "idx_notifications_is_read", columnList = "is_read"),
        @Index(name = "idx_notifications_created_time", columnList = "created_time"),
        @Index(name = "idx_notifications_expire_time", columnList = "expire_time")
})
@Data
@EqualsAndHashCode(exclude = {"user"})
@ToString(exclude = {"user"})
public class Notification {

    // ========== 主键标识 ==========

    /**
     * 通知ID - 主键，自增长
     * 数据库字段：id (BIGINT, PRIMARY KEY, AUTO_INCREMENT)
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // ========== 关联关系 ==========

    /**
     * 用户 - 接收通知的用户
     * 多对一关系，外键关联users表
     * 延迟加载提高性能
     */
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id", nullable = false, foreignKey = @ForeignKey(name = "fk_notifications_user_id"))
    private User user;

    // ========== 通知内容信息 ==========

    /**
     * 通知标题 - 通知消息标题
     * 数据库字段：title (VARCHAR(200)), NOT NULL
     */
    @Column(nullable = false, length = 200)
    private String title;

    /**
     * 通知内容 - 通知详细内容
     * 数据库字段：content (TEXT), NOT NULL
     */
    @Column(nullable = false, columnDefinition = "TEXT")
    private String content;

    // ========== 通知属性信息 ==========

    /**
     * 通知类型 - 通知分类
     * SYSTEM: 系统公告，BORROW: 借阅相关，RETURN: 归还相关，OVERDUE: 逾期提醒，RESERVATION: 预约相关
     * 数据库字段：type (ENUM), DEFAULT 'SYSTEM'
     */
    @Enumerated(EnumType.STRING)
    @Column(nullable = false, length = 20)
    private NotificationType type = NotificationType.SYSTEM;

    /**
     * 优先级 - 通知重要程度
     * LOW: 低，NORMAL: 普通，HIGH: 高，URGENT: 紧急
     * 数据库字段：priority (ENUM), DEFAULT 'NORMAL'
     */
    @Enumerated(EnumType.STRING)
    @Column(nullable = false, length = 20)
    private NotificationPriority priority = NotificationPriority.NORMAL;

    /**
     * 是否已读 - 标记用户是否已阅读
     * 数据库字段：is_read (TINYINT(1)), DEFAULT 0
     */
    @Column(name = "is_read")
    private Boolean isRead = false;

    // ========== 关联业务信息 ==========

    /**
     * 关联业务ID - 关联的业务记录ID
     * 数据库字段：related_id (BIGINT)
     */
    @Column(name = "related_id")
    private Long relatedId;

    /**
     * 关联业务类型 - 关联的业务记录类型
     * 数据库字段：related_type (VARCHAR(50))
     */
    @Column(name = "related_type", length = 50)
    private String relatedType;

    /**
     * 过期时间 - 通知过期时间，过期后不再显示
     * 数据库字段：expire_time (DATETIME)
     */
    @Column(name = "expire_time")
    private LocalDateTime expireTime;

    // ========== 审计字段 ==========

    /**
     * 创建人ID - 通知创建者
     * 数据库字段：created_by (BIGINT)
     */
    @Column(name = "created_by")
    private Long createdBy;

    /**
     * 创建时间 - 通知创建时间，自动生成
     * 数据库字段：created_time (DATETIME), DEFAULT CURRENT_TIMESTAMP
     */
    @CreationTimestamp
    @Column(name = "created_time", updatable = false)
    private LocalDateTime createdTime;

    /**
     * 更新时间 - 通知最后修改时间，自动更新
     * 数据库字段：updated_time (DATETIME), DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
     */
    @UpdateTimestamp
    @Column(name = "updated_time")
    private LocalDateTime updatedTime;

    // ========== 业务方法 ==========

    /**
     * 标记为已读
     * 更新阅读状态和阅读时间
     *
     * @return true-标记成功，false-标记失败
     */
    public boolean markAsRead() {
        if (!this.isRead) {
            this.isRead = true;
            this.updatedTime = LocalDateTime.now();
            return true;
        }
        return false;
    }

    /**
     * 检查通知是否已过期
     * 比较当前时间与过期时间
     *
     * @return true-已过期，false-未过期
     */
    public boolean isExpired() {
        return this.expireTime != null && LocalDateTime.now().isAfter(this.expireTime);
    }

    /**
     * 检查通知是否有效
     * 有效条件：未过期且未删除
     *
     * @return true-有效，false-无效
     */
    public boolean isValid() {
        return !isExpired();
    }

    /**
     * 获取通知年龄（天）
     * 从创建时间到当前时间的天数
     *
     * @return 通知年龄（天）
     */
    public long getNotificationAge() {
        return ChronoUnit.DAYS.between(this.createdTime, LocalDateTime.now());
    }

    /**
     * 检查是否为紧急通知
     * 优先级为URGENT的通知
     *
     * @return true-紧急通知，false-非紧急通知
     */
    public boolean isUrgent() {
        return this.priority == NotificationPriority.URGENT;
    }

    /**
     * 检查是否为系统通知
     * 类型为SYSTEM的通知
     *
     * @return true-系统通知，false-业务通知
     */
    public boolean isSystemNotification() {
        return this.type == NotificationType.SYSTEM;
    }

    /**
     * 获取内容摘要
     * 截取内容前50个字符作为摘要
     *
     * @return 内容摘要
     */
    public String getContentSummary() {
        if (this.content == null || this.content.length() <= 50) {
            return this.content;
        }
        return this.content.substring(0, 50) + "...";
    }

    /**
     * 检查是否即将过期（在指定天数内过期）
     *
     * @param days 提前提醒天数
     * @return true-即将过期，false-未即将过期
     */
    public boolean isExpiringSoon(int days) {
        if (this.expireTime == null) {
            return false; // 永不过期
        }
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime warningDate = this.expireTime.minusDays(days);
        return !now.isBefore(warningDate) && now.isBefore(this.expireTime);
    }
}